package model;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class QueryGraph {

	public static void main(String[] args) throws IOException {
		QueryGraph qg = loadFromTextFile("queryNode.txt", "queryEdge.txt");
		qg.edges.size();
	}

	public ArrayList<QueryNode> nodes = new ArrayList<QueryNode>();
	public ArrayList<QueryEdge> edges = new ArrayList<QueryEdge>();

	// the adjacency matrix of the query graph.
	public QueryAdjacencyList[] adjacencyMatrix;

	public QueryAdjacencyList[] reverseAdjacencyMatrix;

	// the search space of this query. Specified by the data graph.
	public List<List<Integer>> searchSpace;

	// initialize the adjacency matrix of the query graph.
	public void initializeAdjacencyList() {
		this.adjacencyMatrix = new QueryAdjacencyList[this.nodes.size()];
		this.reverseAdjacencyMatrix = new QueryAdjacencyList[this.nodes.size()];

		for (int j = 0; j < this.nodes.size(); j++) {
			this.adjacencyMatrix[j] = new QueryAdjacencyList();
			this.reverseAdjacencyMatrix[j] = new QueryAdjacencyList();
		}
		for (int i = 0; i < this.edges.size(); i++) {
			int sId = this.edges.get(i).getSourceId();
			this.adjacencyMatrix[sId].add(this.edges.get(i));
		}
		for (int i = 0; i < this.edges.size(); i++) {
			int tId = this.edges.get(i).getTargetId();
			this.reverseAdjacencyMatrix[tId].add2(this.edges.get(i));
		}
	}

	// get feasible mates for the graph pattern.
	public void initializeSearchSpace(Graph g) {
		this.searchSpace = new ArrayList<List<Integer>>();
		for (int i = 0; i < this.nodes.size(); i++) {
			this.searchSpace.add(new ArrayList<Integer>());
			for (int j = 0; j < g.nodes.size(); j++) {
				if (g.nodes.get(j).satisfy(this.nodes.get(i))) {
					this.searchSpace.get(i).add(Integer.valueOf(j));
				}
			}
		}
	}

	/**
	 * load query graph from file.
	 * 
	 */
	public static QueryGraph loadFromTextFile(String nodeFileName,
			String edgeFileName) throws IOException {

		System.out.println("Reading query graph from .txt file");
		QueryGraph g = new QueryGraph();

		BufferedReader nodeReader = new BufferedReader(new FileReader(
				nodeFileName));

		BufferedReader edgeReader = new BufferedReader(new FileReader(
				edgeFileName));

		HashMap<String, QueryNode> nodeMap = new HashMap<String, QueryNode>();

		String line = nodeReader.readLine();
		while (line != null) {
			String[] elements = line.split("\t");
			QueryNode n = new QueryNode();
			n.id = elements[0];

			if (elements[1].equalsIgnoreCase("NULL")) {// the second col is
														// label
				n.label = null; // it means this query node doesn't have
								// predicate on the node's label
			} else {
				n.label = elements[1];
			}

			for (int i = 2; i < elements.length; i += 2) { // the rest of
															// columns
															// are attributes.
				if (elements[i].equalsIgnoreCase("NULL")) {
					n.queryAttributes.add(null);
					// it means this query node doesn't have predicate on this
					// attribute
				} else {
					QueryAttribute q = new QueryAttribute(elements[i]);
					if (elements[i + 1].equalsIgnoreCase("<")) {
						q.predicateType = QueryAttribute.PREDICATE_TYPE_LESS_THAN;
					} else if (elements[i + 1].equalsIgnoreCase(">")) {
						q.predicateType = QueryAttribute.PREDICATE_TYPE_LARGER_THAN;
					} else { // =
						q.predicateType = QueryAttribute.PREDICATION_TYPE_EQUAL;
					}
					n.queryAttributes.add(q);
				}

			}

			g.nodes.add(n);
			nodeMap.put(n.id, n);
			line = nodeReader.readLine();
		}
		nodeReader.close();

		line = edgeReader.readLine();
		while (line != null) {
			String[] elements = line.split("\t");

			QueryEdge e = new QueryEdge();
			e.id = elements[0]; // the first col is id

			if (elements[1].equalsIgnoreCase("NULL")) {
				// the second col is label
				e.label = null; // it means this query node doesn't have
				// predicate on the node's label
			} else {
				e.label = elements[1];
			}

			e.sourceNode = nodeMap.get(elements[2]); // the 3rd col is
														// sourceNode id
			e.targetNode = nodeMap.get(elements[3]); // the 4th col is
														// targetNode id

			for (int i = 4; i < elements.length; i += 2) { // the rest of
															// columns
															// are attributes.
				if (elements[i].equalsIgnoreCase("NULL")) {
					e.queryAttributes.add(null);
					// it means this query edge doesn't have predicate on this
					// attribute
				} else {
					QueryAttribute q = new QueryAttribute(elements[i]);
					if (elements[i + 1].equalsIgnoreCase("<")) {
						q.predicateType = QueryAttribute.PREDICATE_TYPE_LESS_THAN;
					} else if (elements[i + 1].equalsIgnoreCase(">")) {
						q.predicateType = QueryAttribute.PREDICATE_TYPE_LARGER_THAN;
					} else { // =
						q.predicateType = QueryAttribute.PREDICATION_TYPE_EQUAL;
					}
					e.queryAttributes.add(q);
				}
			}
			g.edges.add(e);
			line = edgeReader.readLine();
		}
		edgeReader.close();
		System.out.println("Done.");
		return g;
	}
}
